package com.mew.common.dc.db;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mew.common.config.RedisConstantValue;
import com.mew.common.dc.mapper.WinfreeMapper;
import com.mew.common.enm.ExitType;
import com.mew.common.entity.game.WinFree;
import com.mew.common.util.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class WinFreeService {

    @Autowired
    private WinfreeMapper winfreeMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public WinFree getWinFree(long userId, int gameId, int roomId) {
        if (userId <1 || roomId <1){
            return null;
        }

        WinFree winFree = (WinFree)redisTemplate.opsForHash().get(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId));
        if (null != winFree && !NumberUtil.isLtOne(winFree.getId())){
            return winFree;
        }

        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<WinFree>()
                .eq(WinFree::getRoomId, roomId)
                .eq(WinFree::getUserId, userId);
        winFree = winfreeMapper.selectOne(queryWrapper);
        if (null == winFree){
            winFree = createWinFree(userId, gameId, roomId);
        }
        redisTemplate.opsForHash().put(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId), winFree);
        return winFree;
    }

    public WinFree getWinFreeByUser(long userId, int roomId){
        if (userId <1 || roomId <1){
            return null;
        }

        WinFree winFree = (WinFree)redisTemplate.opsForHash().get(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId));
        if (null != winFree && !NumberUtil.isLtOne(winFree.getId())){
            return winFree;
        }

        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<WinFree>()
                .eq(WinFree::getRoomId, roomId)
                .eq(WinFree::getUserId, userId);
        winFree = winfreeMapper.selectOne(queryWrapper);

        if (null == winFree){
            return null;
        }
        redisTemplate.opsForHash().put(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId), winFree);
        return winFree;
    }

    public WinFree getRedisWinfree(long userId, int roomId){
        if (userId <1 || roomId <1){
            return null;
        }
        return (WinFree)redisTemplate.opsForHash().get(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId));
    }


    public WinFree findHaveByUser(long userId){
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<WinFree>()
                .eq(WinFree::getUserId, userId);
        List<WinFree> dbList = winfreeMapper.selectList(queryWrapper);
        if (null == dbList || dbList.isEmpty()){
            return null;
        }

        Collection<String> keys =  dbList.stream().map(winFree -> String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, winFree.getRoomId())).collect(Collectors.toList());
        List<Object> list = redisTemplate.opsForHash().multiGet(RedisConstantValue.USER_WINFREE, Collections.singleton(keys));
        if (null != list && !list.isEmpty()){
            WinFree winFree = list.stream().map(o -> (WinFree)o).filter(wf -> wf.validWinFree()).findAny().orElse(null);
            if (null != winFree){
                return winFree;
            }
        }
        return dbList.stream().filter(wf -> wf.validWinFree()).findAny().orElse(null);
    }




    private WinFree createWinFree(long userId, int gameId, int roomId){
        WinFree winFree = new WinFree();
        winFree.setUserId(userId);
        winFree.setGameId(gameId);
        winFree.setRoomId(roomId);
        winfreeMapper.insert(winFree);
        return winfreeMapper.selectById(winFree.getId());
    }


    public void updateWinfree(long userId, int roomId, ExitType exeStateType){
        if (roomId < 1){
            return;
        }
        WinFree winFree = (WinFree)redisTemplate.opsForHash().get(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId));
        if (null == winFree){
            return;
        }
        winfreeMapper.updateById(winFree);
        if (ExitType.Expires == exeStateType){
            redisTemplate.opsForHash().delete(RedisConstantValue.USER_WINFREE, String.format(RedisConstantValue.USER_WINFREE_TOPIC, userId, roomId));
        }
    }



}
